module renderers.GLSLModel;
import frontend.Types;
import frontend.Model;
import framework.GLSLRenderer;
import derelict.sdl.sdl;
import derelict.opengl.gl;
import derelict.opengl.glu;
import maths.Vec;
import utils.Memory;
import shared.glExtLoader;

enum ModelRendererFunc{
	RenderNothing=0,
	/+RenderNotSkinned,
	RenderBones,+/
	RenderSkinned
}

class ModelRenderer {
	//vec3[] verticesToDraw;
	//vec3[] normalsToDraw;
	this(Model model){
		renderer.register(&this.update);
		this.model=model;
		//verticesToDraw.alloc(model.positions.length);
		//normalsToDraw.alloc(model.positions.length);
	}
	
	private Model model;
	private ModelRendererFunc func=ModelRendererFunc.RenderNothing;
	
	private void update(){
		model.update;
		switch(func){
			//case ModelRendererFunc.RenderNotSkinned: unskinnedRender(); break;
			case ModelRendererFunc.RenderNothing: blankRender(); break;
			//case ModelRendererFunc.RenderBones: renderBones(); break;
			case ModelRendererFunc.RenderSkinned: renderSkinned(); break;
		}
	}
	
	void set(ModelRendererFunc nf){
		func=nf;
	}
	
	private void blankRender(){
		
	}

	/+private void unskinnedRender(){
		
		glDisable(GL_TEXTURE_2D);
		glEnable(GL_LIGHTING);
		glEnable(GL_LIGHT0);
		glEnable(GL_CULL_FACE);
		glEnable(GL_DEPTH_TEST);
		
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		glBegin(GL_TRIANGLES);
		foreach (i; model.indices) {
			glColor3f(1, 1, 1);
			glNormal3fv(&model.normals[i].x);
			glVertex3fv(&model.positions[i].x);
			//writefln(model.normals[i]);
		}
		glEnd();
	}
	
	private void renderBones(){
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);
		glDisable(GL_LIGHT0);
		glDisable(GL_CULL_FACE);
		glDisable(GL_DEPTH_TEST);
		
		Skeleton skeleton=model.skeleton;
		glDisable(GL_TEXTURE_2D);
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		glBegin(GL_LINES);
			glColor3f(1, 0, 0);
			renderBone(skeleton.pelvis);
		glEnd();
	}
	

	
	private void renderBone(Bone* bone){
		foreach(child;bone.children){
			glVertex3fv(&(vec3.convert(bone.coordSys.origin).x));
			glVertex3fv(&(vec3.convert(child.coordSys.origin).x));
		}
		foreach(child;bone.children){
			renderBone(child);
		}
	}+/
	
	private void renderSkinned(){
		/+foreach(index,p;model.positions){
			verticesToDraw[index]=vec3.zero;
			normalsToDraw[index]=vec3.zero;
			foreach(i,bone;model.bones[index]){
				verticesToDraw[index]+=model.weights[index][i]* model.skeleton.rotandtrans[bone].xform(model.offsets[index][i]);
				normalsToDraw[index]+=model.weights[index][i]* model.skeleton.rotonly[bone].xform(model.normals[index]);
			}
			normalsToDraw[index].normalize;
		} +/
		glDisable(GL_TEXTURE_2D);
		glEnable(GL_LIGHTING);
		glEnable(GL_LIGHT0);
		glEnable(GL_CULL_FACE);
		glEnable(GL_DEPTH_TEST);
		
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		
		glUniformMatrix4fvARB(boneMatricesParam, model.skeleton.rotandtrans.length, 0, cast(float*) model.skeleton.rotandtrans);
		
		
		glBegin(GL_TRIANGLES);
		
		foreach (i; model.indices) {
						glVertexAttrib1fARB(numBonesAttrib, cast(float) 1.f);
			            glVertexAttrib3fvARB(normalAttrib, cast (float*)&model.normals[i]);    // normal
                        glVertexAttrib4fvARB(weightAttrib, cast (float*)&vec4(model.weights[i][0],model.weights[i].length>1?model.weights[i][1]:0,model.weights[i].length>2?model.weights[i][2]:0,model.weights[i].length>3?model.weights[i][3]:0));     // weights
                        glVertexAttrib4fvARB(indexAttrib, cast (float*)&vec4(model.bones[i][0],model.bones[i].length>1?model.bones[i][1]:0,model.bones[i].length>2?model.bones[i][2]:0,model.bones[i].length>3?model.bones[i][3]:0));         // indices
						glVertexAttrib3fvARB(positionAttrib, cast (float*)&model.offsets[i][0].x);
						
			//glColor3f(1, 1, 1);
			//glNormal3fv(&normalsToDraw[i].x);
			//glVertex3fv(&verticesToDraw[i].x);
			//writefln(model.normals[i]);
		}
		//writefln("*");
		
		glEnd();
		
		
		/+glDisable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);
		glDisable(GL_LIGHT0);
		glDisable(GL_CULL_FACE);
		glDisable(GL_DEPTH_TEST);
		
		vec4[3] blah;
		blah[0]=vec4(-1,  -1,   -2, 0);
		blah[1]=vec4(1,   -1,   -2, 0);
		blah[2]=vec4(0,    1,   -2, 0);
		
		glBegin(GL_TRIANGLES);
			//glVertex3f(-1,  -1,   -2);
			glVertexAttrib3fvARB(positionAttrib, cast (float*)&blah[0]);
			//glVertex3f(1,   -1,   -2);
			glVertexAttrib3fvARB(positionAttrib, cast (float*)&blah[1]);
			//glVertex3f(0,    1,   -2);
			glVertexAttrib3fvARB(positionAttrib, cast (float*)&blah[2]);
		glEnd();+/
	}
}
import std.stdio;